﻿using CloudApiServer.Class;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static log4net.Appender.RollingFileAppender;

namespace CloudApiServer.Services
{
    /// <summary>
    /// 药店结算服务 
    /// </summary>
    public class FsiDrugStoreService
    {
        /// <summary>
        /// 2101/2101A药店预结算
        /// </summary>
        /// <param name="fsiRequest">预结算入参</param>
        /// <param name="CountrollerName">来源控制器名称</param>
        /// <returns>预结算出参</returns>
        /// <exception cref="Exception"></exception>
        public async Task<outputDrugstoreSettleAccountsPreA> DrugstoreSettleAccountsPre(FsiRequestHeader<InputDrugstoreSettleAccountsPreA> fsiRequest, string CountrollerName)
        {
            List<DrugdetailDrugstoreSettleAccountsPreA> list = new List<DrugdetailDrugstoreSettleAccountsPreA>();
            list = fsiRequest.Input.drugdetail;
            string psn_no = fsiRequest.Input.druginfo.psn_no;
            string fsiadmvs = fsiRequest.mdtrtarea_admvs.Substring(0, 2);
            if (string.IsNullOrEmpty(psn_no) || string.IsNullOrEmpty(fsiRequest.fixmedins_code) || list.Count == 0)
            {
                throw new Exception("参数校验失败：传入的机构代码|人员编号|待结算的商品数组为空，请检查入参！" );
            }
            string connectionString = $"Database={ApiDatainfo.mysqlDatabase};Data Source={ApiDatainfo.mysqlUrl};Port={ApiDatainfo.mysqlPost};UserId={ApiDatainfo.mysqlUser};Password={ApiDatainfo.mysqlPwd};Charset=utf8mb4;TreatTinyAsBoolean=false;Allow User Variables=True";

            using (var conn = new MySqlConnection(connectionString))
            {
                Random rnd = new Random();
                DateTime dateTime = DateTime.Now;
                DataTable dtpsninfo = new DataTable();
                string createTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                await conn.OpenAsync();
                using (MySqlTransaction transaction = conn.BeginTransaction())
                {
                    using (MySqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "select * from fsi_PsnInfo where psn_no=@psn_no";
                        cmd.Parameters.AddWithValue("@psn_no", psn_no);
                        using (MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync())
                        {
                            dtpsninfo.Load(reader);
                            if (dtpsninfo.Rows.Count != 1)
                            {
                                throw new Exception($"查询人员信息表失败！查询到的人员信息总数为：{dtpsninfo.Rows.Count}");
                            }
                            cmd.Parameters.Clear();
                        }
                        string clr_type = "11";
                        if (fsiRequest.Input.druginfo.med_type == "41")
                        {
                            clr_type = "41";
                        }
                        else
                        {
                            clr_type = "11";
                        }
                        string mdtrt_id = rnd.Next(10000000, 90000000).ToString();
                        List<Detlcutinfo> dataList = new List<Detlcutinfo>();
                        foreach (var item in list)
                        {
                            if (fsiRequest.Input.druginfo.med_type != "41")
                            {
                                cmd.CommandText = "SELECT * FROM fsi_prescription_detail a  left JOIN fsi_prescription b  on a.auth_rxno = b.auth_rxno where b.hi_rxno =@hi_rxno  and a.med_list_codg=@med_list_codg ";
                                cmd.Parameters.AddWithValue("@hi_rxno", item.rxno);
                                cmd.Parameters.AddWithValue("@med_list_codg", item.med_list_codg);
                                using (MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync())
                                {
                                    DataTable dt = new DataTable();
                                    dt.Load(reader);
                                    if (dt.Rows.Count < 1)
                                    {
                                        throw new Exception($"处方药品明细校验失败：【{item.med_list_codg}】商品不存于处方【{item.rxno}】中。");
                                    }
                                }
                                cmd.Parameters.Clear();
                            }
                            Detlcutinfo detlcutinfo = new Detlcutinfo
                            {
                                bas_medn_flag = "0",
                                med_chrgitm_type = "09",
                                det_item_fee_sumamt = item.det_item_fee_sumamt,
                                hi_nego_drug_flag = "0",
                                fulamt_ownpay_amt = 0,
                                cnt = item.cnt,
                                pric = item.pric,
                                feedetl_sn = item.feedetl_sn,
                                inscp_scp_amt = item.det_item_fee_sumamt,
                                drt_reim_flag = "0",
                                overlmt_amt = 0,
                                pric_uplmt_amt = item.det_item_fee_sumamt,
                                selfpay_prop = 0,
                                preselfpay_amt = 0,
                                chrgitm_lv = "03"
                            };
                            dataList.Add(detlcutinfo);
                        }
                        List<Setldetail> setldetail = new List<Setldetail>();
                        if (fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay != 0)
                        {
                            Setldetail detail = new Setldetail
                            {
                                fund_pay_type = "310200",
                                fund_payamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2),
                                setl_proc_info = null,
                                crt_payb_lmt_amt = 0,
                                inscp_scp_amt = 0,
                                fund_pay_type_name = "城镇职工基本医疗保险个人账户基金"
                            };
                            setldetail.Add(detail);
                        }
                        if (fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt != 0)
                        {
                            Setldetail detail = new Setldetail
                            {
                                fund_pay_type = "310100",
                                fund_payamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, 2),
                                setl_proc_info = null,
                                crt_payb_lmt_amt = 0,
                                inscp_scp_amt = 0,
                                fund_pay_type_name = "城镇职工基本医疗保险统筹基金"
                            };
                            setldetail.Add(detail);
                        }
                        var output = new outputDrugstoreSettleAccountsPreA
                        {
                            detlcutinfo = dataList,
                            setlinfo = new Setlinfo
                            {
                                setl_time = dateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                                cvlserv_pay = FsiDatainfo.cvlserv_pay,//公务员医疗补助资金
                                hifdm_pay = FsiDatainfo.hifdm_pay,//伤残人员医疗保障基金支出
                                cvlserv_flag = dtpsninfo.Rows[0]["cvlserv_flag"].ToString(),//公务员标志
                                med_type = fsiRequest.Input.druginfo.med_type,
                                brdy = dtpsninfo.Rows[0]["brdy"].ToString(),
                                naty = dtpsninfo.Rows[0]["naty"].ToString(),//民族

                                psn_cash_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.psn_cash_pay, 2),//现金支付

                                certno = fsiRequest.Input.druginfo.exp_content.certno ?? dtpsninfo.Rows[0]["certno"].ToString(),//身份证号码
                                hifmi_pay = FsiDatainfo.hifmi_pay,//居民大病保险资金支出
                                psn_no = fsiRequest.Input.druginfo.psn_no,
                                act_pay_dedc = FsiDatainfo.act_pay_dedc,//实际支付起付线
                                mdtrt_cert_type = fsiRequest.Input.druginfo.mdtrt_cert_type,

                                balc = Math.Round(Convert.ToDouble(dtpsninfo.Rows[0]["balc"]) - Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2), 2),
                                medins_setl_id = $"{fsiRequest.fixmedins_code}{dateTime.ToString("yyyyMMddHHmmssffff")}",
                                psn_cert_type = fsiRequest.Input.druginfo.exp_content.psn_cert_type ?? dtpsninfo.Rows[0]["psn_cert_type"].ToString(),
                                acct_mulaid_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_mulaid_pay, 2),//个人账户共济支付金额
                                clr_way = "1",
                                hifob_pay = FsiDatainfo.hifob_pay,//职工大额医疗费用补助基金支出
                                oth_pay = FsiDatainfo.oth_pay,//其他支出
                                medfee_sumamt = fsiRequest.Input.druginfo.medfee_sumamt,
                                hifes_pay = FsiDatainfo.hifes_pay,//企业补充医疗保险基金支出
                                gend = dtpsninfo.Rows[0]["gend"].ToString(),
                                mdtrt_id = mdtrt_id,

                                acct_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2),//个人账户支出

                                fund_pay_sumamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, 2),//基金支付

                                fulamt_ownpay_amt = FsiDatainfo.fulamt_ownpay_amt,//全自费金额
                                hosp_part_amt = FsiDatainfo.hosp_part_amt,//医院负担金额
                                inscp_scp_amt = FsiDatainfo.inscp_scp_amt,//符合政策范围金额
                                insutype = fsiRequest.Input.druginfo.insutype,
                                maf_pay = FsiDatainfo.maf_pay, //医疗救助基金支出
                                psn_name = fsiRequest.Input.druginfo.exp_content.psn_name ?? dtpsninfo.Rows[0]["psn_name"].ToString(),
                                psn_part_amt = fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, //个人负担总额
                                clr_optins = null,
                                pool_prop_selfpay = FsiDatainfo.fund_pay_sumamt, //基本医疗保险统筹基金支付比例
                                psn_type = fsiRequest.Input.druginfo.exp_content.psn_type ?? dtpsninfo.Rows[0]["psn_type"].ToString(),
                                hifp_pay = fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, //基本医疗保险统筹基金支出
                                overlmt_selfpay = FsiDatainfo.overlmt_selfpay, //超限价金额
                                preselfpay_amt = FsiDatainfo.preselfpay_amt, //先行自付金额
                                age = PublicMethod.CalculateAge(Convert.ToDateTime(dtpsninfo.Rows[0]["brdy"]), dateTime),
                                clr_type = clr_type,
                            },
                            setldetail = setldetail
                        };
                        string OutputJson = JsonConvert.SerializeObject(output);
                        string InputJson = JsonConvert.SerializeObject(fsiRequest);
                        cmd.Transaction = transaction;
                        try
                        {
                            cmd.CommandText = "INSERT INTO fsi_order  VALUES (null, @fixmedins_code,@fixmedins_name,@order_state,@med_type,@psn_no,@setl_id,@mdtrt_id, @SettleAccountspreAInput,@SettleAccountspreAOutput,@SettleAccountsAInput,@SettleAccountsAOutput,@RevokeInput,@RevokeOutput,@create_time,@update_time)";
                            cmd.Parameters.AddWithValue("@fixmedins_code", fsiRequest.fixmedins_code);
                            cmd.Parameters.AddWithValue("@fixmedins_name", fsiRequest.fixmedins_name);
                            cmd.Parameters.AddWithValue("@order_state", 0);
                            cmd.Parameters.AddWithValue("@med_type", fsiRequest.Input.druginfo.med_type);
                            cmd.Parameters.AddWithValue("@psn_no", fsiRequest.Input.druginfo.psn_no);
                            cmd.Parameters.AddWithValue("@setl_id", "");
                            cmd.Parameters.AddWithValue("@mdtrt_id", mdtrt_id);
                            cmd.Parameters.AddWithValue("@SettleAccountspreAInput", InputJson);
                            cmd.Parameters.AddWithValue("@SettleAccountspreAOutput", OutputJson);
                            cmd.Parameters.AddWithValue("@SettleAccountsAInput", "");
                            cmd.Parameters.AddWithValue("@SettleAccountsAOutput", "");
                            cmd.Parameters.AddWithValue("@RevokeInput", "");
                            cmd.Parameters.AddWithValue("@RevokeOutput", "");
                            cmd.Parameters.AddWithValue("@create_time", dateTime.ToString("yyyy-MM-dd HH-mm-ss"));
                            cmd.Parameters.AddWithValue("@update_time", dateTime.ToString("yyyy-MM-dd HH-mm-ss"));
                            await cmd.ExecuteNonQueryAsync();
                            cmd.Parameters.Clear();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            throw new Exception($"预结算处理失败：插入订单记录失败！错误内容：{ex.Message} 异常来源：{ex.StackTrace}");
                        }
                        transaction.Commit();
                        return output;
                    }
                }
            }
        }
        
        /// <summary>
        /// 2102/2102A药店结算
        /// </summary>
        /// <param name="fsiRequest">结算入参</param>
        /// <param name="CountrollerName">来源控制器名称</param>
        /// <returns>结算出参</returns>
        /// <exception cref="Exception"></exception>
        public async Task<outputDrugstoreSettleAccountsPreA> DrugstoreSettleAccounts(FsiRequestHeader<InputDrugstoreSettleAccountsPreA> fsiRequest, string CountrollerName)
        {
            List<DrugdetailDrugstoreSettleAccountsPreA> list = new List<DrugdetailDrugstoreSettleAccountsPreA>();
            list = fsiRequest.Input.drugdetail;
            string psn_no = fsiRequest.Input.druginfo.psn_no;
            string fsiadmvs = fsiRequest.mdtrtarea_admvs.Substring(0, 2);
            if (string.IsNullOrEmpty(psn_no) || string.IsNullOrEmpty(fsiRequest.fixmedins_code) || list.Count == 0)
            {
                throw new Exception("参数校验失败：传入的机构代码|人员编号|待结算的商品数组为空，请检查入参！");
            }
            string connectionString = $"Database={ApiDatainfo.mysqlDatabase};Data Source={ApiDatainfo.mysqlUrl};Port={ApiDatainfo.mysqlPost};UserId={ApiDatainfo.mysqlUser};Password={ApiDatainfo.mysqlPwd};Charset=utf8mb4;TreatTinyAsBoolean=false;Allow User Variables=True";

            using (var conn = new MySqlConnection(connectionString))
            {
                Random rnd = new Random();
                DateTime dateTime = DateTime.Now;
                DataTable dtpsninfo = new DataTable();
                long dtunix = PublicMethod.ConvertToUnixTimestampMillis(dateTime);
                string createTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                await conn.OpenAsync();
                using (MySqlTransaction transaction = conn.BeginTransaction())
                {
                    using (MySqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "select * from fsi_PsnInfo where psn_no=@psn_no";
                        cmd.Parameters.AddWithValue("@psn_no", psn_no);
                        using (MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync())
                        {
                            dtpsninfo.Load(reader);
                            if (dtpsninfo.Rows.Count != 1)
                            {
                                throw new Exception($"查询人员信息表失败！查询到的人员信息总数为：{dtpsninfo.Rows.Count}");
                            }
                            cmd.Parameters.Clear();
                        }
                        string clr_type = "11";
                        if (fsiRequest.Input.druginfo.med_type == "41")
                        {
                            clr_type = "41";
                        }
                        else
                        {
                            clr_type = "11";
                        }
                        //设置结算id与就诊id
                        string mdtrt_id;
                        string setl_id;
                        //浙江省 如果是异地 则结算id需要短一点，不然会报错 模拟异地的结算id长度 取人员参保地长度前四位是否和入参参保地前四位是否一致
                        if (CountrollerName == "FsiApiZheJiangController" && fsiadmvs =="33" && fsiRequest.insuplc_admdvs.Substring(0, 4) != fsiRequest.mdtrtarea_admvs.Substring(0, 4))
                        {
                            mdtrt_id = $"{dtunix}";
                            setl_id = $"{fsiadmvs}0000{dtunix}000{rnd.Next(10000000, 90000000).ToString()}";
                        }
                        else
                        {
                            mdtrt_id = $"{fsiadmvs}0000{dtunix}000{rnd.Next(10000000, 90000000).ToString()}";
                            setl_id = $"{fsiadmvs}0000{dtunix}000{rnd.Next(10000000, 90000000).ToString()}";
                        }
                        //设置出参数商品列表
                        List<Detlcutinfo> dataList = new List<Detlcutinfo>();
                        //设置插入历史购药费用明细数组列表
                        List<FsiQuerydrugdosagInsert> FsiQuerydrugdosagInsertList = new List<FsiQuerydrugdosagInsert>();
                        foreach (var item in list)
                        {
                            Detlcutinfo detlcutinfo = new Detlcutinfo
                            {
                                bas_medn_flag = "0",
                                med_chrgitm_type = "09",
                                det_item_fee_sumamt = item.det_item_fee_sumamt,
                                hi_nego_drug_flag = "0",
                                fulamt_ownpay_amt = 0,
                                cnt = item.cnt,
                                pric = item.pric,
                                feedetl_sn = item.feedetl_sn,
                                inscp_scp_amt = item.det_item_fee_sumamt,
                                drt_reim_flag = "0",
                                overlmt_amt = 0,
                                pric_uplmt_amt = item.det_item_fee_sumamt,
                                selfpay_prop = 0,
                                preselfpay_amt = 0,
                                chrgitm_lv = "03"
                            };
                            dataList.Add(detlcutinfo);
                            FsiQuerydrugdosagInsert FsiQuerydrugdosagInsert = new FsiQuerydrugdosagInsert
                            {
                                mdtrtId = setl_id,
                                feeOcurTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                                hilistCode = item.med_list_codg,
                                psnno = psn_no,
                                fixmedins_code = fsiRequest.fixmedins_code,
                                fixmedins_name = fsiRequest.fixmedins_name,
                                usedFrquDscr = item.used_frqu_dscr,
                                sinDosDscr = item.sin_dos_dscr,
                                cnt = item.cnt,
                                medinsListCodg = item.medins_list_codg,
                                chrgitmLv = item.chrgitm_lv,
                                pric = item.pric,
                                detItemFeeSumamt = item.det_item_fee_sumamt,
                                bilgDrCode = item.bilg_dr_codg,
                                bilgDrName = item.bilg_dr_name,
                                ds = dateTime.ToString("yyyyMMdd")
                            };
                            FsiQuerydrugdosagInsertList.Add(FsiQuerydrugdosagInsert);
                        }
                        //序列化结算当年历年拓展字段
                        Setlinfoexpcontent setlinfoexpcontent = new Setlinfoexpcontent
                        {
                            clcYearAcctPay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.clcYearAcctPay, 2),
                            Q0001 = 0,
                            crtYearAcctPay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.crtYearAcctPay, 2)
                        };
                        string expcontentJson = JsonConvert.SerializeObject(setlinfoexpcontent);
                        //设置结算明细数组
                        List<Setldetail> setldetail = new List<Setldetail>();
                        if (fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay != 0)
                        {
                            Setldetail detail = new Setldetail
                            {
                                fund_pay_type = "310200",
                                fund_payamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2),
                                setl_proc_info = null,
                                crt_payb_lmt_amt = 0,
                                inscp_scp_amt = 0,
                                fund_pay_type_name = "城镇职工基本医疗保险个人账户基金"
                            };
                            setldetail.Add(detail);
                        }
                        if (fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt != 0)
                        {
                            Setldetail detail = new Setldetail
                            {
                                fund_pay_type = "310100",
                                fund_payamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, 2),
                                setl_proc_info = null,
                                crt_payb_lmt_amt = 0,
                                inscp_scp_amt = 0,
                                fund_pay_type_name = "城镇职工基本医疗保险统筹基金"
                            };
                            setldetail.Add(detail);
                        }


                        //Setldetail detail1 = new Setldetail
                        //{
                        //    fund_pay_type = "650102",
                        //    fund_payamt = 11,
                        //    setl_proc_info = null,
                        //    crt_payb_lmt_amt = 0,
                        //    inscp_scp_amt = 0,
                        //    fund_pay_type_name = "罕见病用药"
                        //};
                        //setldetail.Add(detail1);
                        var output = new outputDrugstoreSettleAccountsPreA
                        {
                            detlcutinfo = dataList,
                            setlinfo = new Setlinfo
                            {
                                setl_time = dateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                                cvlserv_pay = FsiDatainfo.cvlserv_pay,//公务员医疗补助资金
                                hifdm_pay = FsiDatainfo.hifdm_pay,//伤残人员医疗保障基金支出
                                cvlserv_flag = dtpsninfo.Rows[0]["cvlserv_flag"].ToString(),//公务员标志
                                med_type = fsiRequest.Input.druginfo.med_type,
                                exp_content = expcontentJson,
                                brdy = dtpsninfo.Rows[0]["brdy"].ToString(),
                                naty = dtpsninfo.Rows[0]["naty"].ToString(),//民族
                                psn_cash_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.psn_cash_pay, 2),//现金支付
                                certno = fsiRequest.Input.druginfo.exp_content.certno ?? dtpsninfo.Rows[0]["certno"].ToString(),//身份证号码
                                hifmi_pay = FsiDatainfo.hifmi_pay,//居民大病保险资金支出
                                psn_no = fsiRequest.Input.druginfo.psn_no,
                                act_pay_dedc = FsiDatainfo.act_pay_dedc,//实际支付起付线
                                mdtrt_cert_type = fsiRequest.Input.druginfo.mdtrt_cert_type,

                                balc = Math.Round(Convert.ToDouble(dtpsninfo.Rows[0]["balc"]) - Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2), 2),
                                medins_setl_id = $"{fsiRequest.fixmedins_code}{dateTime.ToString("yyyyMMddHHmmssffff")}",
                                psn_cert_type = fsiRequest.Input.druginfo.exp_content.psn_cert_type ?? dtpsninfo.Rows[0]["psn_cert_type"].ToString(),
                                acct_mulaid_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_mulaid_pay, 2),//个人账户共济支付金额
                                clr_way = "1",
                                hifob_pay = FsiDatainfo.hifob_pay,//职工大额医疗费用补助基金支出
                                oth_pay = FsiDatainfo.oth_pay,//其他支出
                                medfee_sumamt = fsiRequest.Input.druginfo.medfee_sumamt,
                                hifes_pay = FsiDatainfo.hifes_pay,//企业补充医疗保险基金支出
                                gend = dtpsninfo.Rows[0]["gend"].ToString(),
                                mdtrt_id = mdtrt_id,
                                acct_pay = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.acct_pay, 2),//个人账户支出
                                fund_pay_sumamt = Math.Round(fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, 2),//基金支付
                                fulamt_ownpay_amt = FsiDatainfo.fulamt_ownpay_amt,//全自费金额
                                hosp_part_amt = FsiDatainfo.hosp_part_amt,//医院负担金额
                                setl_id = setl_id,
                                inscp_scp_amt = FsiDatainfo.inscp_scp_amt,//符合政策范围金额
                                insutype = fsiRequest.Input.druginfo.insutype,
                                maf_pay = FsiDatainfo.maf_pay, //医疗救助基金支出
                                psn_name = fsiRequest.Input.druginfo.exp_content.psn_name ?? dtpsninfo.Rows[0]["psn_name"].ToString(),
                                psn_part_amt = fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, //个人负担总额
                                clr_optins = null,
                                pool_prop_selfpay = FsiDatainfo.fund_pay_sumamt, //基本医疗保险统筹基金支付比例
                                psn_type = fsiRequest.Input.druginfo.exp_content.psn_type ?? dtpsninfo.Rows[0]["psn_type"].ToString(),
                                hifp_pay = fsiRequest.Input.druginfo.medfee_sumamt * FsiDatainfo.fund_pay_sumamt, //基本医疗保险统筹基金支出
                                overlmt_selfpay = FsiDatainfo.overlmt_selfpay, //超限价金额
                                preselfpay_amt = FsiDatainfo.preselfpay_amt, //先行自付金额
                                age = PublicMethod.CalculateAge(Convert.ToDateTime(dtpsninfo.Rows[0]["brdy"]), dateTime),
                                clr_type = clr_type,
                            },
                            setldetail = setldetail
                        };
                        string OutputJson = JsonConvert.SerializeObject(output);
                        string InputJson = JsonConvert.SerializeObject(fsiRequest);
                        cmd.Transaction = transaction;
                        try
                        {
                            //插入历史购药费用明细
                            bool InsertquerydrugdosagState = await PublicMethod.FsiInsertquerydrugdosag(FsiQuerydrugdosagInsertList);
                            if (InsertquerydrugdosagState == false)
                            {
                                throw new Exception("插入历史费用明细失败!");
                            }
                            //插入订单汇总记录
                            cmd.CommandText = "INSERT INTO fsi_order  VALUES (null, @fixmedins_code,@fixmedins_name,@order_state,@med_type,@psn_no,@setl_id,@mdtrt_id, @SettleAccountspreAInput,@SettleAccountspreAOutput,@SettleAccountsAInput,@SettleAccountsAOutput,@RevokeInput,@RevokeOutput,@create_time,@update_time)";
                            cmd.Parameters.AddWithValue("@fixmedins_code", fsiRequest.fixmedins_code);
                            cmd.Parameters.AddWithValue("@fixmedins_name", fsiRequest.fixmedins_name);
                            cmd.Parameters.AddWithValue("@order_state", 1);
                            cmd.Parameters.AddWithValue("@med_type", fsiRequest.Input.druginfo.med_type);
                            cmd.Parameters.AddWithValue("@psn_no", fsiRequest.Input.druginfo.psn_no);
                            cmd.Parameters.AddWithValue("@setl_id", setl_id);
                            cmd.Parameters.AddWithValue("@mdtrt_id", mdtrt_id);
                            cmd.Parameters.AddWithValue("@SettleAccountspreAInput", "");
                            cmd.Parameters.AddWithValue("@SettleAccountspreAOutput", "");
                            cmd.Parameters.AddWithValue("@SettleAccountsAInput", InputJson);
                            cmd.Parameters.AddWithValue("@SettleAccountsAOutput", OutputJson);
                            cmd.Parameters.AddWithValue("@RevokeInput", "");
                            cmd.Parameters.AddWithValue("@RevokeOutput", "");
                            cmd.Parameters.AddWithValue("@create_time", dateTime.ToString("yyyy-MM-dd HH-mm-ss"));
                            cmd.Parameters.AddWithValue("@update_time", dateTime.ToString("yyyy-MM-dd HH-mm-ss"));
                            await cmd.ExecuteNonQueryAsync();
                            cmd.Parameters.Clear();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            throw new Exception($"结算处理失败：插入订单记录失败！错误内容：{ex.Message} 异常来源：{ex.StackTrace}");
                        }
                        //插入年度费用累计
                        try
                        {
                            cmd.CommandText = "INSERT INTO fsi_queryfixmedinspracpsnsum  VALUES (@psn_no,@cum_type_code,@year,@cum,@cum_ym,@insutype)";
                            cmd.Parameters.AddWithValue("@psn_no", fsiRequest.Input.druginfo.psn_no);
                            cmd.Parameters.AddWithValue("@cum_type_code", "S1100");
                            cmd.Parameters.AddWithValue("@year", dateTime.ToString("yyyy"));
                            cmd.Parameters.AddWithValue("@cum", fsiRequest.Input.druginfo.medfee_sumamt);
                            cmd.Parameters.AddWithValue("@cum_ym", dateTime.ToString("yyyyMM"));
                            cmd.Parameters.AddWithValue("@insutype", dtpsninfo.Rows[0]["insutype"]);
                            await cmd.ExecuteNonQueryAsync();
                            cmd.Parameters.Clear();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            throw new Exception($"结算处理失败：插入费用累计记录失败！错误内容：{ex.Message} 异常来源：{ex.StackTrace}");
                        }
                        transaction.Commit();
                        //Console.WriteLine("ok 参数组织完成进入等待！\r\n"+FsiHeader);
                        //Thread.Sleep(60000);
                        return output;
                    }
                }
            }
        }

        /// <summary>
        /// 2103药店结算撤销
        /// </summary>
        /// <param name="fsiRequest">撤销结算入参</param>
        /// <param name="CountrollerName">来源控制器名称</param>
        /// <returns>撤销结算出参</returns>
        /// <exception cref="Exception"></exception>
        public async Task<outputDrugstoreSettleRevoke> DrugstoreSettleRevoke(FsiRequestHeader<InputDrugstoreSettleRevokeRequest> fsiRequest, string CountrollerName)
        {
            string fsiadmvs = fsiRequest.mdtrtarea_admvs.Substring(0, 2);
            string fixmedins_code = fsiRequest.fixmedins_code;
            string setl_id = fsiRequest.Input.data.setl_id;
            string psn_no = fsiRequest.Input.data.psn_no;
            string mdtrtid = fsiRequest.Input.data.mdtrt_id;
            if (string.IsNullOrEmpty(fixmedins_code) || string.IsNullOrEmpty(psn_no) || string.IsNullOrEmpty(mdtrtid) || string.IsNullOrEmpty(setl_id))
            {
                throw new Exception("参数校验失败：传入的结算id|人员编号||就诊ID为空，请检查入参！");
            }
            string connectionString = $"Database={ApiDatainfo.mysqlDatabase};Data Source={ApiDatainfo.mysqlUrl};Port={ApiDatainfo.mysqlPost};UserId={ApiDatainfo.mysqlUser};Password={ApiDatainfo.mysqlPwd};Charset=utf8mb4;TreatTinyAsBoolean=false;Allow User Variables=True";

            using (var conn = new MySqlConnection(connectionString))
            {
                Random rnd = new Random();
                DateTime dateTime = DateTime.Now;
                DataTable dtpsninfo = new DataTable();
                DataTable dt = new DataTable();
                string createTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
                long dtunix = PublicMethod.ConvertToUnixTimestampMillis(dateTime);
                await conn.OpenAsync();
                using (MySqlTransaction transaction = conn.BeginTransaction())
                {
                    using (MySqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "select * from fsi_PsnInfo where psn_no=@psn_no";
                        cmd.Parameters.AddWithValue("@psn_no", psn_no);
                        using (MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync())
                        {
                            dtpsninfo.Load(reader);
                            if (dtpsninfo.Rows.Count != 1)
                            {
                                throw new Exception($"查询人员信息表失败！查询到的人员信息总数为：{dtpsninfo.Rows.Count}");
                            }
                            cmd.Parameters.Clear();
                        }
                        cmd.CommandText = "select * from fsi_order where psn_no=@psn_no and mdtrt_id=@mdtrt_id and setl_id=@setl_id and order_state=1";
                        cmd.Parameters.AddWithValue("@psn_no", psn_no);
                        cmd.Parameters.AddWithValue("@mdtrt_id", mdtrtid);
                        cmd.Parameters.AddWithValue("@setl_id", setl_id);
                        using (MySqlDataReader reader = (MySqlDataReader)await cmd.ExecuteReaderAsync())
                        {
                            dt.Load(reader);
                            if (dt.Rows.Count != 1)
                            {
                                throw new Exception($"查询已结算的订单信息表失败！查询到的订单信息总数为：{dt.Rows.Count}");
                            }
                            cmd.Parameters.Clear();
                        }

                        string SettleAccountsAOutput = dt.Rows[0]["SettleAccountsAOutput"].ToString();
                        if (string.IsNullOrEmpty(SettleAccountsAOutput))
                        {
                            throw new Exception($"参数校验失败：根据传入的参数已找到订单但结算信息为空！");
                        }
                        outputDrugstoreSettleAccountsPreA FsiHeaderSettleAccountsPreA = JsonConvert.DeserializeObject<outputDrugstoreSettleAccountsPreA>(SettleAccountsAOutput);
                        List<Setldetail> list = new List<Setldetail>();
                        list = FsiHeaderSettleAccountsPreA.setldetail;
                        List<Setldetail> dataList = new List<Setldetail>();
                        foreach (var item in list)
                        {
                            //序列化基金支付风项
                            setl_proc_info setlinfoexpcontent = new setl_proc_info
                            {
                                hifpPayInscp = item.fund_payamt,
                                polItemCode = "LA01",
                                poolPropSelfpay = 0,
                                hifpPay = item.fund_payamt
                            };

                            string expcontentJson = JsonConvert.SerializeObject(setlinfoexpcontent);
                            if (item.fund_pay_type == "310200")
                            {
                                Setldetail setldetail = new Setldetail
                                {
                                    fund_pay_type = item.fund_pay_type,
                                    fund_payamt = 0 - item.fund_payamt,
                                    setl_proc_info = expcontentJson,
                                    crt_payb_lmt_amt = 0 - item.crt_payb_lmt_amt,
                                    inscp_scp_amt = 0 - item.inscp_scp_amt,
                                    fund_pay_type_name = item.fund_pay_type_name
                                };
                                dataList.Add(setldetail);
                            }
                            else
                            {
                                Setldetail setldetail = new Setldetail
                                {
                                    fund_pay_type = item.fund_pay_type,
                                    fund_payamt = 0 - item.fund_payamt,
                                    setl_proc_info = null,
                                    crt_payb_lmt_amt = 0 - item.crt_payb_lmt_amt,
                                    inscp_scp_amt = 0 - item.inscp_scp_amt,
                                    fund_pay_type_name = item.fund_pay_type_name
                                };
                                dataList.Add(setldetail);
                            }
                        }
                        var output = new outputDrugstoreSettleRevoke
                        {
                            setlinfo = new SetlinfoRevoke
                            {
                                setl_time = dateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                                cvlserv_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.cvlserv_pay,
                                hifdm_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.hifdm_pay,
                                psn_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.psn_cash_pay,
                                hifmi_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.hifmi_pay,
                                act_pay_dedc = 0 - FsiHeaderSettleAccountsPreA.setlinfo.act_pay_dedc,
                                balc = FsiHeaderSettleAccountsPreA.setlinfo.balc + FsiHeaderSettleAccountsPreA.setlinfo.acct_pay,
                                medins_setl_id = $"{fixmedins_code}{dateTime.ToString("yyyyMMddHHmmssffff")}",
                                acct_mulaid_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.acct_mulaid_pay,
                                hifob_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.hifob_pay,
                                oth_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.oth_pay,
                                medfee_sumamt = 0 - FsiHeaderSettleAccountsPreA.setlinfo.medfee_sumamt,
                                hifes_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.hifes_pay,
                                mdtrt_id = mdtrtid,
                                acct_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.acct_pay,
                                fund_pay_sumamt = 0 - FsiHeaderSettleAccountsPreA.setlinfo.fund_pay_sumamt,
                                fulamt_ownpay_amt = 0 - FsiHeaderSettleAccountsPreA.setlinfo.fulamt_ownpay_amt,
                                setl_id = $"{fsiadmvs}0000{dtunix}000{rnd.Next(10000000, 90000000).ToString()}",
                                inscp_scp_amt = 0 - FsiHeaderSettleAccountsPreA.setlinfo.inscp_scp_amt,
                                maf_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.maf_pay,
                                clr_optins = $"{fsiRequest.mdtrtarea_admvs.Substring(0, 4)}99",
                                pool_prop_selfpay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.pool_prop_selfpay,
                                hifp_pay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.hifp_pay,
                                overlmt_selfpay = 0 - FsiHeaderSettleAccountsPreA.setlinfo.overlmt_selfpay,
                                preselfpay_amt = 0 - FsiHeaderSettleAccountsPreA.setlinfo.preselfpay_amt
                            },
                            setldetail = dataList
                        };
                        string OutputJson = JsonConvert.SerializeObject(output);
                        string InputJson = JsonConvert.SerializeObject(fsiRequest);
                        cmd.Transaction = transaction;
                        try
                        {
                            cmd.CommandText = "update fsi_order  set order_state= @order_state,RevokeInput=@RevokeInput,RevokeOutput=@RevokeOutput,update_time=@update_time where psn_no=@psn_no and mdtrt_id=@mdtrt_id and setl_id=@setl_id and order_state=1";
                            cmd.Parameters.AddWithValue("@order_state", 1);
                            cmd.Parameters.AddWithValue("@RevokeInput", InputJson);
                            cmd.Parameters.AddWithValue("@RevokeOutput", OutputJson);
                            cmd.Parameters.AddWithValue("@update_time", dateTime.ToString("yyyy-MM-dd HH-mm-ss"));
                            cmd.Parameters.AddWithValue("@psn_no", psn_no);
                            cmd.Parameters.AddWithValue("@mdtrt_id", mdtrtid);
                            cmd.Parameters.AddWithValue("@setl_id", setl_id);
                            await cmd.ExecuteNonQueryAsync();
                            cmd.Parameters.Clear();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            throw new Exception($"退款数据处理失败：更新订单记录失败！错误内容：{ex.Message} 异常来源：{ex.StackTrace}");
                        }
                        try
                        {
                            cmd.CommandText = "INSERT INTO fsi_queryfixmedinspracpsnsum  VALUES (@psn_no,@cum_type_code,@year,@cum,@cum_ym,@insutype)";
                            cmd.Parameters.AddWithValue("@psn_no", psn_no);
                            cmd.Parameters.AddWithValue("@cum_type_code", "S1100");
                            cmd.Parameters.AddWithValue("@year", dateTime.ToString("yyyy"));
                            cmd.Parameters.AddWithValue("@cum", 0 - FsiHeaderSettleAccountsPreA.setlinfo.medfee_sumamt);
                            cmd.Parameters.AddWithValue("@cum_ym", dateTime.ToString("yyyyMM"));
                            cmd.Parameters.AddWithValue("@insutype", dtpsninfo.Rows[0]["insutype"]);
                            await cmd.ExecuteNonQueryAsync();
                            cmd.Parameters.Clear();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            throw new Exception($"退款数据处理失败：插入费用累计记录失败！错误内容：{ex.Message} 异常来源：{ex.StackTrace}");
                        }
                        transaction.Commit();
                        return output;
                    }
                }
            }
        }
    }
}
